{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.datasets import fetch_mldata\n",
    "import numpy as np\n",
    "import pandas as pd \n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 数据集读取\n",
    "mnist = fetch_mldata('mnist-original', data_home='./')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 数据\n",
    "X=mnist['data']\n",
    "y=mnist['target']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 洗牌 \n",
    "shuffle_index=np.random.permutation(70000)\n",
    "# 数据\n",
    "X=X[shuffle_index]\n",
    "# 标签\n",
    "y=y[shuffle_index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(70000, 784) (70000,)\n"
     ]
    }
   ],
   "source": [
    "print(X.shape,y.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 训练集，测试集拆分\n",
    "X_train,y_train,X_test,y_test=X[:60000,:],y[:60000],X[60000:,:],y[60000:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# data_new=X_train.reshape((len(X_train),int(np.sqrt(X_train.shape[1])),-1))\n",
    "# data_new.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n/w/B7wpRYTx0OQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x19e770185f8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 图片展示\n",
    "%matplotlib inline\n",
    "some_digit=X_train[40000]\n",
    "some_digit_img=some_digit.reshape(28,28)\n",
    "plt.imshow(some_digit_img,cmap=matplotlib.cm.binary)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def image_offset(data_s,dir='u',offset=1):\n",
    "    data_r=data_s.reshape((len(data_s), -1))\n",
    "    data_new=[]\n",
    "    if dir=='u':\n",
    "        for img_data in data_r:\n",
    "            img_data_new=np.concatenate((img_data[offset:,:],img_data[:offset,:]),axis=0)\n",
    "            data_new.append(img_data_new)\n",
    "        \n",
    "    elif dir=='d':\n",
    "        for img_data in data_r:\n",
    "            img_data_new=np.concatenate((img_data[(len(img_data)-offset):,:],img_data[:(len(img_data)-offset),:]),axis=0)\n",
    "            data_new.append(img_data_new)\n",
    "            \n",
    "    elif dir=='l':\n",
    "        for img_data in data_r:\n",
    "            img_data_new=np.concatenate((img_data[:,offset:],img_data[:,:offset]),axis=1)\n",
    "            data_new.append(img_data_new)\n",
    "            \n",
    "    elif dir=='r':\n",
    "        for img_data in data_r:\n",
    "            img_data_new=np.concatenate((img_data[:,(len(img_data)-offset):],img_data[:,:(len(img_data)-offset)]),axis=1)\n",
    "            data_new.append(img_data_new)\n",
    "    data_new=np.array(data_new)        \n",
    "    X_train=data_new.reshape(len(data_s),-1)\n",
    "    return X_train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_train_u=image_offset(X_train,dir='u')\n",
    "X_train_d=image_offset(X_train,dir='d')\n",
    "X_train_l=image_offset(X_train,dir='l')\n",
    "X_train_r=image_offset(X_train,dir='r')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_train_new=np.concatenate((X_train,X_train_u,X_train_d,X_train_l,X_train_r),axis=0)\n",
    "y_train_new=np.concatenate((y_train,y_train,y_train,y_train,y_train),axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 实例化 \n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "kn_clf=KNeighborsClassifier()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "           metric_params=None, n_jobs=1, n_neighbors=5, p=2,\n",
       "           weights='uniform')"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 填充数据\n",
    "kn_clf.fit(X_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6.])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 验证\n",
    "kn_clf.predict([some_digit])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_score,recall_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.model_selection import cross_val_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.model_selection import cross_val_predict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False, False, ..., False, False, False])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_5=(y_train.astype(int)==5)\n",
    "y_train_5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "           metric_params=None, n_jobs=1, n_neighbors=5, p=2,\n",
       "           weights='uniform')"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kn_clf.fit(X_train,y_train_5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "y_train_pred=cross_val_predict(kn_clf,X_train,y_train_5,cv=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "precision:97.2%\n",
      "recall:95.3%\n"
     ]
    }
   ],
   "source": [
    "# 精度，召回\n",
    "precision=precision_score(y_train_5,y_train_pred)\n",
    "recall=recall_score(y_train_5,y_train_pred)\n",
    "print('precision:{:.1f}%'.format(precision*100))\n",
    "print('recall:{:.1f}%'.format(recall*100))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "kn_clf_new=KNeighborsClassifier()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "y_train_new_5=(y_train_new.astype(int)==5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "           metric_params=None, n_jobs=1, n_neighbors=5, p=2,\n",
       "           weights='uniform')"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kn_clf_new.fit(X_train_new,y_train_new_5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "kn_clf_new.predict([some_digit])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "y_train_new_pred=cross_val_predict(kn_clf_new,X_train_new,y_train_new_5,cv=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "precision=precision_score(y_train_new_5,y_train_new_pred)\n",
    "recall=recall_score(y_train_new_5,y_train_new_pred)\n",
    "print('precision:{:.1f}%'.format(precision*100))\n",
    "print('recall:{:.1f}%'.format(recall*100))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "y_test_5=(y_test.astype(int)==5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "y_test_pred=cross_val_predict(kn_clf_new,X_test,y_test_5,cv=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "precision=precision_score(y_test_5,y_test_pred)\n",
    "recall=recall_score(y_test_5,y_test_pred)\n",
    "print('precision:{:.1f}%'.format(precision*100))\n",
    "print('recall:{:.1f}%'.format(recall*100))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 结论\n",
    "- 没有进行数据增广的表现：\n",
    "    - precision:97.0%\n",
    "    - recall:95.5%\n",
    "- 像素位移后，模型表现\n",
    "    - precision:98.0%\n",
    "    - recall:97.2%\n",
    "- 测试集表现\n",
    "    - precision:95.3%\n",
    "    - recall:91.1%\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
